package com.sob.bountyhunter;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.newdawn.slick.Animation;
import org.newdawn.slick.Color;
import org.newdawn.slick.Image;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.SpriteSheet;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class Art {
	//Tabla para las animaciones con cuatro direcciones
	private static HashMap <String, Animation[]> anims;
	
	/**
	 * Obtiene una animacion (con varias direcciones posibles) guardada
	 * @param name Nombre de la animacion
	 * @return
	 */
	public static Animation[] getAnim(String name){		
		Animation[] anim=null;
		
		Animation[] tAnim=anims.get(name);
		anim=new Animation[tAnim.length];
		
		//Copia la animacion y devuelve la copia 
		//(Temporal, no se si seria mejor crearla desde el archivo para que ocupe menos memoria)
		for(int i=0;i<anim.length;i++){
			anim[i]=tAnim[i].copy();
		}
		
		
		return anim;
	}
	
	/**
	 * Carga una animacion desde un archivo xml
	 * @param fileName Ruta del archivo (sin el .xml)
	 * @throws ParserConfigurationException
	 * @throws SAXException
	 * @throws IOException
	 * @throws SlickException
	 */
	public static void loadAnimation(String fileName) throws ParserConfigurationException, SAXException, IOException, SlickException{
		XmlAnimDef []defs=loadXmlAnimFile(fileName);
		
		//Si, aun no se ha inicializado la tabla, lo hace
		if(anims==null){
			anims=new HashMap<String, Animation[]>();
		}
		
		//Carga y guarda la animacion
		for(XmlAnimDef animDef: defs){
			Animation[] anim=loadPngAnimFile(animDef);
			anims.put(animDef.name, anim);			
		}
	}
		
	private static Animation[] loadPngAnimFile(XmlAnimDef animDef) throws SlickException{
		
		Animation []animacion;		
		//Carga la plantilla
		SpriteSheet archivo=new SpriteSheet("/res/anims/"+animDef.file, animDef.spriteWidth, animDef.spriteHeight, new Color(0xFF00FF));
		
		//Define las animaciones para las X direcciones
		animacion=new Animation[animDef.numDirs];
		for(int i=0;i<animDef.numDirs;i++){
			animacion[i]=new Animation();
			animacion[i].setAutoUpdate(false);
			
			//Define cada frame
			for(int j=0;j<animDef.frameTime.length;j++){
				Image img=archivo.getSubImage(j, i+animDef.startRow);
				animacion[i].addFrame(img, animDef.frameTime[j]);				
			}
		}
		
		return animacion;
	}
	
	private static XmlAnimDef[] loadXmlAnimFile(String fileName) throws ParserConfigurationException, SAXException, IOException{
		File file=new File(fileName+".xml");
		DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
		DocumentBuilder db=dbf.newDocumentBuilder();
		Document doc=db.parse(file);
		//doc.getDocumentElement().normalize();
		
		//Obtiene la lista de elementos Animation
		NodeList animsList=doc.getElementsByTagName("animation");
		XmlAnimDef []animDefs=new XmlAnimDef[animsList.getLength()];
		
		//Los recorre
		for(int i=0;i<animsList.getLength();i++){
			
			Element animElemt=(Element) animsList.item(i);
			
			//Obtiene los atributos
			String name=animElemt.getAttribute("name");
			String pngFileName=animElemt.getAttribute("file");
			String spriteWidth=animElemt.getAttribute("spriteWidth");
			String spriteHeight=animElemt.getAttribute("spriteHeight");
			String frames=animElemt.getAttribute("frames");
			String numDirs=animElemt.getAttribute("numDirs");
			String defaultTme=animElemt.getAttribute("defaultTime");
			String startRow=animElemt.getAttribute("startRow");
			
			//Guarda los atributos
			animDefs[i]=new XmlAnimDef(frames);
			animDefs[i].name=name;
			animDefs[i].file=pngFileName;
			animDefs[i].setSpriteWidth(spriteWidth);
			animDefs[i].setSpriteHeight(spriteHeight);
			animDefs[i].setStartRow(startRow);
			animDefs[i].setNumDirs(numDirs);
			animDefs[i].setDefaultTime(defaultTme);
			
			//Recorre la definicion de frames (opcional)
			NodeList frameList=animElemt.getElementsByTagName("frame");
			for(int j=0;j<frameList.getLength();j++){
				Element frameElemt=(Element) frameList.item(j);
				
				//Obtiene atributos y los guarda
				String frameNum=frameElemt.getAttribute("num");
				String frameTime=frameElemt.getAttribute("time");				
				animDefs[i].setTime(frameNum, frameTime);
			}
		}
		
		return animDefs; 
	}
}
